﻿namespace Devonline.Security;

/// <summary>
/// 对称算法密钥
/// 此对象为加解密前的数据组成
/// </summary>
public class KeyIV
{
    /// <summary>
    /// 对称加密算法 Key 的长度, AES 256 CBC 模式下默认 32
    /// </summary>
    public int KeySize { get; private set; }
    /// <summary>
    /// 对称加密算法 IV 的长度, 默认 16
    /// </summary>
    public int IVSize { get; private set; }
    /// <summary>
    /// Key 编号
    /// </summary>
    public long Id { get; private set; }
    /// <summary>
    /// 对称算法 Key 的值
    /// </summary>
    public byte[] Key { get; private set; }
    /// <summary>
    /// 对称算法 IV 的值
    /// </summary>
    public byte[] IV { get; private set; }
    /// <summary>
    /// 对称算法密钥组成: Id(8)+KeySize(4)+IVSize(4)+Key+IV
    /// </summary>
    public byte[] Value { get; private set; }
    /// <summary>
    /// 已使用次数
    /// </summary>
    public int UsedCount { get; private set; } = 0;
    /// <summary>
    /// 创建时间
    /// </summary>
    public DateTime CreatedTime { get; private set; } = DateTime.UtcNow;

    /// <summary>
    /// 使用 key 和 iv 初始化密钥数据
    /// 此构造方法用于从原始的 Key 和 IV 生成待加密的完整密钥数据
    /// </summary>
    /// <param name="id">对称加密算法的编号 </param>
    /// <param name="key">对称加密算法的 Key</param>
    /// <param name="iv">对称加密算法的 IV</param>
    public KeyIV(long id, byte[] key, byte[] iv)
    {
        Id = id;
        Key = key;
        IV = iv;
        KeySize = key.Length;
        IVSize = iv.Length;
        Value = new byte[KeySize + IVSize + AppSettings.UNIT_SIXTEEN];
        var bytes = BitConverter.GetBytes(Id);
        Array.Copy(bytes, AppSettings.UNIT_ZERO, Value, AppSettings.UNIT_ZERO, AppSettings.UNIT_EIGHT);
        bytes = BitConverter.GetBytes(KeySize);
        Array.Copy(bytes, AppSettings.UNIT_ZERO, Value, AppSettings.UNIT_EIGHT, AppSettings.UNIT_FOUR);
        bytes = BitConverter.GetBytes(IVSize);
        Array.Copy(bytes, AppSettings.UNIT_ZERO, Value, AppSettings.UNIT_EIGHT + AppSettings.UNIT_FOUR, AppSettings.UNIT_FOUR);
        Array.Copy(Key, AppSettings.UNIT_ZERO, Value, AppSettings.UNIT_SIXTEEN, KeySize);
        Array.Copy(IV, AppSettings.UNIT_ZERO, Value, KeySize + AppSettings.UNIT_SIXTEEN, IVSize);
    }
    /// <summary>
    /// 使用 value 初始化密钥数据
    /// 此构造方法用于密钥解密后的明文还原 Key 和 IV
    /// </summary>
    /// <param name="value">对称算法的密钥完整部分</param>
    public KeyIV(byte[] value)
    {
        Value = value;
        Id = BitConverter.ToInt64(value);
        KeySize = BitConverter.ToInt32(value, AppSettings.UNIT_EIGHT);
        IVSize = BitConverter.ToInt32(value, AppSettings.UNIT_EIGHT + AppSettings.UNIT_FOUR);
        Key = new byte[KeySize];
        IV = new byte[IVSize];
        Array.Copy(Value, AppSettings.UNIT_SIXTEEN, Key, AppSettings.UNIT_ZERO, KeySize);
        Array.Copy(Value, AppSettings.UNIT_SIXTEEN + KeySize, IV, AppSettings.UNIT_ZERO, IVSize);
    }

    /// <summary>
    /// 设置使用次数
    /// </summary>
    public void Used() => UsedCount++;
}